package com.qingxin.sys.dao;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * HQL语句查询类
 */
public class Querier {
	
	private StringBuilder hqlBuilder;

	private List<String> params;
	private List<Object> values;

	private List<String> paramsList;
	private List<Collection<Object>> valuesList;

	private List<String> paramsArray;
	private List<Object[]> valuesArray;

	private int firstResult = 0;//第一条记录索引，从0开始

	private int maxResults = 0;

	private boolean cacheable = false;

	public static final String ROW_COUNT = "select count(*) ";
	public static final String FROM = "from";
	public static final String DISTINCT = "distinct";
	public static final String HQL_FETCH = "fetch";
	public static final String ORDER_BY = "order";
	
	
	private Querier() {
		hqlBuilder = new StringBuilder();
	}

	
	private Querier(String hql) {
		hqlBuilder = new StringBuilder(hql);
	}

	
	/**
	 * 创建一个新的查询对象
	 * @return
	 */
	public static Querier create() {
		return new Querier();
	}

	/**
	 * 使用给定HQL创建一个查询对象
	 * @param hql
	 * @return
	 */
	public static Querier create(String hql) {
		return new Querier(hql);
	}

	/**
	 * 在查询对象中追加HQL
	 * @param hql
	 * @return
	 */
	public Querier append(String hql) {
		hqlBuilder.append(hql);
		return this;
	}

	
	/**
	 * 设置参数值
	 * @param param
	 * @param value
	 * @return
	 */
	public Querier setParam(String param, Object value) {
		getParams().add(param);
		getValues().add(value);
		return this;
	}
	
	
	/**
	 * 设置参数值
	 * @param name
	 * @param vals
	 * @return
	 */
	public Querier setParamList(String name, Collection<Object> vals) {
		getParamsList().add(name);
		getValuesList().add(vals);
		return this;
	}

	
	/**
	 * 设置参数值
	 * @param name
	 * @param vals
	 * @return
	 */
	public Querier setParamList(String name, Object[] vals) {
		getParamsArray().add(name);
		getValuesArray().add(vals);
		return this;
	}
	
	
	/**
	 * 获得hql语句
	 * @return
	 */
	public String getHql() {
		return hqlBuilder.toString();
	}

	
	/**
	 * 获得统计记录总数的hql语句
	 * @return
	 */
	public String getCountHql() {
		String hql = hqlBuilder.toString();

		int fromIndex = indexOfPattern(hql, "\\bfrom\\b");
		String projectionHql = hql.substring(0, fromIndex);

		hql = hql.substring(fromIndex);
		String rowCountHql = hql.replace(HQL_FETCH, "");

		int index = indexOfPattern(rowCountHql, "\\border\\b");
		if (index > 0) {
			rowCountHql = rowCountHql.substring(0, index);
		}
		return wrapProjection(projectionHql) + rowCountHql;
	}
	
	private int indexOfPattern(String str, String searchPattern){
		Pattern pattern = Pattern.compile(searchPattern, Pattern.CASE_INSENSITIVE);
		Matcher matcher = pattern.matcher(str);
		if(matcher.find()){
			return matcher.start();
		}
		return -1;
	}
	
	private String wrapProjection(String projection) {
		if (projection.indexOf("select") == -1 || projection.indexOf(" new ") != -1) {
			return ROW_COUNT;
		}else{
			return projection.replace("select", "select count(") + ") ";
		}
	}
	
	
	
	public int getFirstResult() {
		return firstResult;
	}

	public void setFirstResult(int firstResult) {
		this.firstResult = firstResult;
	}

	public int getMaxResults() {
		return maxResults;
	}

	public void setMaxResults(int maxResults) {
		this.maxResults = maxResults;
	}

	
	/**
	 * 是否使用查询缓存
	 * @return
	 */
	public boolean isCacheable() {
		return cacheable;
	}

	/**
	 * 是否使用查询缓存
	 * @param cacheable
	 */
	public void setCacheable(boolean cacheable) {
		this.cacheable = cacheable;
	}

	
//	/**
//	 * 将Querier中的参数设置到org.hibernate.Query中。
//	 * 
//	 * @param query
//	 */
//	public Query setParamsToQuery(Query query) {
//		if (params != null) {
//			for (int i = 0; i < params.size(); i++) {
//				if (types.get(i) == null) {
//					query.setParameter(params.get(i), values.get(i));
//				} else {
//					query.setParameter(params.get(i), values.get(i), types.get(i));
//				}
//			}
//		}
//		if (paramsList != null) {
//			for (int i = 0; i < paramsList.size(); i++) {
//				if (typesList.get(i) == null) {
//					query.setParameterList(paramsList.get(i), valuesList.get(i));
//				} else {
//					query.setParameterList(paramsList.get(i), valuesList.get(i), typesList.get(i));
//				}
//			}
//		}
//		if (paramsArray != null) {
//			for (int i = 0; i < paramsArray.size(); i++) {
//				if (typesArray.get(i) == null) {
//					query.setParameterList(paramsArray.get(i), valuesArray.get(i));
//				} else {
//					query.setParameterList(paramsArray.get(i), valuesArray.get(i), typesArray.get(i));
//				}
//			}
//		}
//		return query;
//	}
//
//	public Query createQuery(Session session) {
//		Query query = setParamsToQuery(session.createQuery(getHql()));
//		if (getFirstResult() > 0) {
//			query.setFirstResult(getFirstResult());
//		}
//		if (getMaxResults() > 0) {
//			query.setMaxResults(getMaxResults());
//		}
//		if (isCacheable()) {
//			query.setCacheable(true);
//		}
//		return query;
//	}

	

	public List<String> getParams() {
		if (params == null) {
			params = new ArrayList<String>();
		}
		return params;
	}

	public List<Object> getValues() {
		if (values == null) {
			values = new ArrayList<Object>();
		}
		return values;
	}

	public List<String> getParamsList() {
		if (paramsList == null) {
			paramsList = new ArrayList<String>();
		}
		return paramsList;
	}

	public List<Collection<Object>> getValuesList() {
		if (valuesList == null) {
			valuesList = new ArrayList<Collection<Object>>();
		}
		return valuesList;
	}

	public List<String> getParamsArray() {
		if (paramsArray == null) {
			paramsArray = new ArrayList<String>();
		}
		return paramsArray;
	}

	public List<Object[]> getValuesArray() {
		if (valuesArray == null) {
			valuesArray = new ArrayList<Object[]>();
		}
		return valuesArray;
	}


	public static void main(String[] args) {
		Querier find = Querier.create("select distinct p FROM BookType join fetch p");
		System.out.println(find.getCountHql());
		System.out.println(find.getHql());
	}

}